<template>
  <div class="tree-node" :class="{'is-current':tree.store.currentNode === node}">
      <div class="tree-node_content" 
        @click="handleClick"
        :style="{ 'padding-left':(node.level*15)+'px' }"
        >
          <p style="display:inline-block;margin:0;">
            <span class="tree-node_expand-icon glyphicon" @click="handleExpandIconHandle" :class="{'glyphicon-chevron-right':!node.expanded,'glyphicon-chevron-down':node.expanded}"></span>
            <input ref="checkbox" v-if="showCheckbox" class="node-checkbox" v-model="node.checked" 
                  :disabled="node.disabled" type="checkbox" @click.native.stop 
                  @change="handleCheckChange(node.checked,$event)"
              />
            <span class="node-loading" v-if="node.loading"><loading></loading></span>
          </p>
          <node-content :node="node"></node-content>
      </div>
      <div class="tree-node_children" v-show="expanded">
          <tree-node v-if="node.childNodes" v-for="child in node.childNodes" 
          :node="child"
          :render-content="renderContent"
          :key="getNodeKey(child)"
          @node-expand="handleChildrenExpand"
          ></tree-node>
      </div>
  </div>
</template>

<script>
import loading from "@/components/loading";
import emitter from "@/utils/emitter";
import { getNodeKey } from "./util";
export default {
  name: "TreeNode",
  componentName: "TreeNode",
  mixins: [emitter],
  data() {
    return {
      expanded: false,
      tree: null,
      showCheckbox: false,
      childNodeRendered: false
    };
  },
  props: {
    renderContent:Function,
    node: {
      default() {
        return {};
      }
    },
    props: {}
  },
  components: {
    loading,
    NodeContent:{
      props:{
        node:{
          required:true
        }
      },
      render(h){
        const parent = this.$parent;
        const tree = parent.tree;
        const node = this.node;
        const { data, store } = node;
        return (
          parent.renderContent
          ? parent.renderContent.call(parent._prenderProxy, h, {_self:tree.$vnode.content, node, data, store})
          : tree.$scopedSlots.default
          ? tree.$scopedSlots.default({node, data})
          :<span class="tree-node_label">{this.node.label}</span>
        )
      }
    }
  },
  watch: {
    "node.expanded": function(val) {
      this.$nextTick(() => {
        this.expanded = val;
      });
    }
  },
  name: "tree-node",
  methods: {
    getNodeKey(node) {
      return getNodeKey(this.tree.nodeKey, node.data);
    },
    handleClick(ev) {
      const checkbox = this.$refs.checkbox;
      if (checkbox === ev.target) return;
      const store = this.tree.store;
      store.setCurrentNode(this.node);
      this.tree.$emit(
        "current-change",
        store.currentNode ? store.currentNode.data : null,
        store.currentNode
      );
      if (this.tree.expandOnClickNode) {
        this.handleExpandIconHandle();
      }
      this.tree.$emit("node-click", this.node.data, this.node, this);
    },
    handleExpandIconHandle() {
      if (this.expanded) {
        this.node.collapse();
      } else {
        this.node.expand();
      }
    },
    handleChildrenExpand(nodeData, node, instance) {
      this.broadcast("TreeNode", "tree-node-expand", node);
      this.tree.$emit("node-expand", nodeData, node, instance);
    },
    handleCheckChange(value, event) {
      this.node.setChecked(event.target.checked, this.tree.checkedStrictly);
      const setChildState = function(node) {
        if (node.childNodes.length === 0) return;
        for (let i = 0, j = node.childNodes.length; i < j; i++) {
          let n = node.childNodes[i];
          if(n.disabled) return;
          n.setChecked(event.target.checked, false);
          if (n.childNodes.length != 0) {
            setChildState(n);
          }
        }
      };
      this.$nextTick(() => {
        setChildState(this.node);
      });
    }
  },
  created() {
    const parent = this.$parent;
    if (parent.isTree) {
      this.tree = parent;
    } else {
      this.tree = parent.tree;
    }
    const tree = this.tree;
    if (!tree) {
      console.warn("Cant not find node's tree");
    }
    const props = tree.props || {};
    const childrenKey = props["children"] || "children";
    this.$watch(`node.data.${childrenKey}`, () => {
      // this.node.updateChildren();
    });
    this.showCheckbox = tree.showCheckbox;

    if (this.node.expanded) {
      this.expanded = true;
      this.childNodeRendered = true;
    }
    if (this.tree.accordion) {
      this.$on("tree-node-expand", node => {
        if (this.node !== node) {
          this.node.collapse();
        }
      });
    }
  }
};
</script>

<style lang="scss" scoped>
.tree-node {
  outline: none;
  white-space: nowrap;
  background: #fff;
  .tree-node_content {
    width:100%;
    display: flex;
    align-items: center;
    height: 26px;
    cursor: pointer;
    .node-checkbox {
      margin: -4px 2px 0 -2px;
      padding: 0;
      vertical-align: middle;
    }
    .node-loading {
      width: 20px;
      height: 15px;
      margin: 0 3px;
    }
  }
  .tree-node_children {
    display: block;
    overflow: hidden;
    background: transparent;
  }
  &.is-current {
    &>div.tree-node_content {
      background:#f5f7fa;
    }    
  }
}
</style>
